﻿using System;
using System.Collections.Generic;
using System.Text;

namespace ExtensionsLib.Dictionary
{

    public static class DictionaryExtensionsGetValue
    {


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TReturn"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <param name="_default"></param>
        /// <param name="hasDefaultValue"></param>
        /// <returns></returns>
        private static TReturn GetValue<TKey, TValue, TReturn>(this IDictionary<TKey, TValue> self, TKey key, TReturn _default, bool hasDefaultValue)
        {
            if (self.ContainsKey(key))
            {
                return self[key].Cast<TReturn>();
            }
            else
            {
                if (hasDefaultValue)
                {
                    return _default;
                }
                else
                {
                    throw new Exception("Dictionary does not contain the key \"" + key.Cast<string>() + "\" !");
                }
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TReturn"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <param name="_default"></param>
        /// <returns></returns>
        public static TReturn GetValue<TKey, TValue, TReturn>(this IDictionary<TKey, TValue> self, TKey key, TReturn _default)
        {
            return self.GetValue<TKey, TValue, TReturn>(key, _default, true);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <param name="_default"></param>
        /// <returns></returns>
        public static TValue GetValue<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key, TValue _default)
        {
            return self.GetValue<TKey, TValue, TValue>(key, _default, true);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TReturn"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static TReturn GetValue<TKey, TValue, TReturn>(this IDictionary<TKey, TValue> self, TKey key)
        {
            return self.GetValue<TKey, TValue, TReturn>(key, default(TReturn), false);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static TValue GetValue<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key)
        {
            return self.GetValue<TKey, TValue, TValue>(key, default(TValue), false);
        }



        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <typeparam name="TReturn"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool TryGetValue<TKey, TValue, TReturn>(this IDictionary<TKey, TValue> self, TKey key, out TReturn value)
        {
            TValue fetchedValue;
            if (self.TryGetValue(key, out fetchedValue))
            {
                value = fetchedValue.Cast<TReturn>();
                return true;
            }
            else
            {
                value = default(TReturn);
                return false;
            }
        }

        
       
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="self"></param>
        /// <param name="key"></param>
        /// <param name="newValue"></param>
        /// <returns></returns>
        public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> self, TKey key, TValue newValue)
        {
            TValue value;
            if (false == self.TryGetValue(key, out value))
            {
                value = newValue;
                self.Add(key, value);
            }
            return value;
        }

      






    }
}
